Assignment 1

1.1

Word cloud for OneTwo.txt

# word cloud for OneTwo.txt
df1$doc_id=1:nrow(df1)
colnames(df1)[1]<-"text"
#Here we interpret each line in the document as separate document
mycorpus <- Corpus(DataframeSource(df1)) #Creating corpus (collection of text data)
mycorpus <- tm_map(mycorpus, removePunctuation)
mycorpus <- tm_map(mycorpus, function(x) removeWords(x, stopwords("english")))
tdm <- TermDocumentMatrix(mycorpus) #Creating term-document matrix
m <- as.matrix(tdm)
#here we merge all rows
v <- sort(rowSums(m),decreasing=TRUE) #Sum up the frequencies of each word
d <- data.frame(word = names(v),freq=v) #Create one column=names, second=frequences
pal <- brewer.pal(8,"Dark2")
pal <- pal[-(1:2)] #Create palette of colors
wordcloud(d$word,d$freq, scale=c(8,.3),min.freq=2,max.words=100, random.order=F, rot.per=.15, colors=pal, vfont=c("sans serif","plain"))

Word cloud for Five.txt

# wordcloud for Five.txt
df2$doc_id=1:nrow(df2)
colnames(df2)[1]<-"text"
#Here we interpret each line in the document as separate document
mycorpus <- Corpus(DataframeSource(df2)) #Creating corpus (collection of text data)
mycorpus <- tm_map(mycorpus, removePunctuation)
mycorpus <- tm_map(mycorpus, function(x) removeWords(x, stopwords("english")))
tdm <- TermDocumentMatrix(mycorpus) #Creating term-document matrix
m <- as.matrix(tdm)
#here we merge all rows
v <- sort(rowSums(m),decreasing=TRUE) #Sum up the frequencies of each word
d <- data.frame(word = names(v),freq=v) #Create one column=names, second=frequences
pal <- brewer.pal(5,"Dark2")
pal <- pal[-(1:2)] #Create palette of colors
wordcloud(d$word,d$freq, scale=c(8,.3),min.freq=2,max.words=100, random.order=F, rot.per=.15, colors=pal, vfont=c("sans serif","plain"))

1.2

Phrase nets for Five.Txt and OneTwo.Txt with connector words

Phrase net for Five.txt

Phrase net for Five.txt

Phrase net for OneTwo.txt

Phrase net for OneTwo.txt

1.3

Word Trees

Assignment 2

# Olive data
olive <- read.csv("olive.csv", sep = ",", header = TRUE)
# convert region to factor
olive$Region <-as.factor(olive$Region)
olive_shared <- SharedData$new(olive)

2.1

eic_lin_scatt <- olive_shared %>% 
  plot_ly(x = ~linoleic, y =~ eicosenoic) #%>%
  #add_markers(list(size = 6, color = "orange"))

We found, for unusually low observations of Eicosenoic it takes the values of 1,2,and 3.

2.2

bar_chart <- olive_shared %>%
  plot_ly( x =~ Region) %>%
  add_histogram() %>%
  layout(barmode = "overlay")
bar_chart
# linking the scatterplot and bar chart
subplot(eic_lin_scatt, bar_chart) %>%
  highlight(on = "plotly_select", dynamic = T, persistent = T, opacityDim = I(1)) %>%
  hide_legend()
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
Adding more colors to the selection color palette.
We recommend setting `persistent` to `FALSE` (the default) because persistent selection mode can now be used by holding the shift key (while triggering the `on` event).
Setting the `off` event (i.e., 'plotly_relayout') to match the `on` event (i.e., 'plotly_selected'). You can change this default via the `highlight()` function.
Setting the `off` event (i.e., 'plotly_relayout') to match the `on` event (i.e., 'plotly_selected'). You can change this default via the `highlight()` function.

bscols(widths=c(2, NA),filter_slider("S", "Stearic", olive_shared, ~stearic)
        ,subplot(eic_lin_scatt, bar_chart)%>%
  highlight(on="plotly_select", dynamic=T, persistent = T, opacityDim = I(1))%>%hide_legend())
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
Adding more colors to the selection color palette.
We recommend setting `persistent` to `FALSE` (the default) because persistent selection mode can now be used by holding the shift key (while triggering the `on` event).
Setting the `off` event (i.e., 'plotly_relayout') to match the `on` event (i.e., 'plotly_selected'). You can change this default via the `highlight()` function.
Setting the `off` event (i.e., 'plotly_relayout') to match the `on` event (i.e., 'plotly_selected'). You can change this default via the `highlight()` function.

2.3

ara_lin_scatt <- olive_shared %>% 
  plot_ly(x = ~linolenic, y =~ arachidic)
subplot(eic_lin_scatt, ara_lin_scatt) %>%
  highlight(on = "plotly_select", dynamic = T, persistent = T, opacityDim = I(1)) %>%
  hide_legend()
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
No trace type specified:
  Based on info supplied, a 'scatter' trace seems appropriate.
  Read more about this trace type -> https://plot.ly/r/reference/#scatter
No scatter mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
Adding more colors to the selection color palette.
We recommend setting `persistent` to `FALSE` (the default) because persistent selection mode can now be used by holding the shift key (while triggering the `on` event).
Setting the `off` event (i.e., 'plotly_relayout') to match the `on` event (i.e., 'plotly_selected'). You can change this default via the `highlight()` function.
Setting the `off` event (i.e., 'plotly_relayout') to match the `on` event (i.e., 'plotly_selected'). You can change this default via the `highlight()` function.

2.4

# the eight acids (column 4:11)
parcord <- ggparcoord(olive, columns = c(3:10))
# plotly_data returns data associated with a plotly visualization.
p_data <- plotly_data(ggplotly(parcord)) %>% group_by(.ID)
par_plot <- plot_ly(shared1, x = ~variable, y =~value) %>%
  add_lines(line = list(width = 0.3)) %>%
  add_markers(marker = list(size = 0.3),
              text = ~.ID, hoverinfo = "text") 
bscols(par_plot%>%highlight(on="plotly_select", dynamic=T, persistent = T, opacityDim = I(1))%>%
         hide_legend(),
       region_bar%>%highlight(on="plotly_click", dynamic=T, persistent = T)%>%hide_legend())
ps<-htmltools::tagList(par_plot%>%
  highlight(on="plotly_select", dynamic=T, persistent = T, opacityDim = I(1))%>%
  hide_legend(),
  region_bar%>%
    highlight(on="plotly_click", dynamic=T, persistent = T, opacityDim = I(1))%>%
    hide_legend()
  )
htmltools::browsable(ps)
# ignore this
subplot(par_plot, region_bar, nrows =2) %>%
  highlight(on="plotly_select", dynamic=T, persistent = T, opacityDim = I(1))%>%
  hide_legend()

Appendix

library(ggplot2)
library(plotly)
library(tm)
library(wordcloud)
library(RColorBrewer)
library(crosstalk)
library(GGally)
library(htmltools)
df1<-read.table("OneTwo.txt",header=F, sep='\n') #Read file
df2<-read.table("Five.txt",header=F, sep='\n')
# word cloud for OneTwo.txt
df1$doc_id=1:nrow(df1)
colnames(df1)[1]<-"text"

#Here we interpret each line in the document as separate document
mycorpus <- Corpus(DataframeSource(df1)) #Creating corpus (collection of text data)
mycorpus <- tm_map(mycorpus, removePunctuation)
mycorpus <- tm_map(mycorpus, function(x) removeWords(x, stopwords("english")))
tdm <- TermDocumentMatrix(mycorpus) #Creating term-document matrix
m <- as.matrix(tdm)

#here we merge all rows
v <- sort(rowSums(m),decreasing=TRUE) #Sum up the frequencies of each word
d <- data.frame(word = names(v),freq=v) #Create one column=names, second=frequences
pal <- brewer.pal(8,"Dark2")
pal <- pal[-(1:2)] #Create palette of colors
wordcloud(d$word,d$freq, scale=c(8,.3),min.freq=2,max.words=100, random.order=F, rot.per=.15, colors=pal, vfont=c("sans serif","plain"))
# wordcloud for Five.txt

df2$doc_id=1:nrow(df2)
colnames(df2)[1]<-"text"

#Here we interpret each line in the document as separate document
mycorpus <- Corpus(DataframeSource(df2)) #Creating corpus (collection of text data)
mycorpus <- tm_map(mycorpus, removePunctuation)
mycorpus <- tm_map(mycorpus, function(x) removeWords(x, stopwords("english")))
tdm <- TermDocumentMatrix(mycorpus) #Creating term-document matrix
m <- as.matrix(tdm)

#here we merge all rows
v <- sort(rowSums(m),decreasing=TRUE) #Sum up the frequencies of each word
d <- data.frame(word = names(v),freq=v) #Create one column=names, second=frequences
pal <- brewer.pal(5,"Dark2")
pal <- pal[-(1:2)] #Create palette of colors
wordcloud(d$word,d$freq, scale=c(8,.3),min.freq=2,max.words=100, random.order=F, rot.per=.15, colors=pal, vfont=c("sans serif","plain"))
# Olive data
olive <- read.csv("olive.csv", sep = ",", header = TRUE)

# convert region to factor
olive$Region <-as.factor(olive$Region)
olive_shared <- SharedData$new(olive)
eic_lin_scatt <- olive_shared %>% 
  plot_ly(x = ~linoleic, y =~ eicosenoic) #%>%
  #add_markers(list(size = 6, color = "orange"))
bar_chart <- olive_shared %>%
  plot_ly( x =~ Region) %>%
  add_histogram() %>%
  layout(barmode = "overlay")

bar_chart
# linking the scatterplot and bar chart
subplot(eic_lin_scatt, bar_chart) %>%
  highlight(on = "plotly_select", dynamic = T, persistent = T, opacityDim = I(1)) %>%
  hide_legend()

bscols(widths=c(2, NA),filter_slider("S", "Stearic", olive_shared, ~stearic)
        ,subplot(eic_lin_scatt, bar_chart)%>%
  highlight(on="plotly_select", dynamic=T, persistent = T, opacityDim = I(1))%>%hide_legend())
ara_lin_scatt <- olive_shared %>% 
  plot_ly(x = ~linolenic, y =~ arachidic)

subplot(eic_lin_scatt, ara_lin_scatt) %>%
  highlight(on = "plotly_select", dynamic = T, persistent = T, opacityDim = I(1)) %>%
  hide_legend()
# the eight acids (column 4:11)
parcord <- ggparcoord(olive, columns = c(3:10))
# plotly_data returns data associated with a plotly visualization.
p_data <- plotly_data(ggplotly(parcord)) %>% group_by(.ID)
# data for crosstalk
shared1<-SharedData$new(p_data, ~.ID, group = "Olive")
par_plot <- plot_ly(shared1, x = ~variable, y =~value) %>%
  add_lines(line = list(width = 0.3)) %>%
  add_markers(marker = list(size = 0.3),
              text = ~.ID, hoverinfo = "text") 

# subset
olive2 <- olive

# create an id
olive2$.ID <- 1:nrow(olive)

# shared data 2
shared2 <- SharedData$new(olive2, ~.ID, group = "olive")
# bar graph of region
region_bar <- shared2 %>%
  plot_ly( x =~ Region) %>%
  add_histogram() %>%
  layout(barmode = "overlay")

bscols(par_plot%>%highlight(on="plotly_select", dynamic=T, persistent = T, opacityDim = I(1))%>%
         hide_legend(),
       region_bar%>%highlight(on="plotly_click", dynamic=T, persistent = T)%>%hide_legend())
ps<-htmltools::tagList(par_plot%>%
  highlight(on="plotly_select", dynamic=T, persistent = T, opacityDim = I(1))%>%
  hide_legend(),
  region_bar%>%
    highlight(on="plotly_click", dynamic=T, persistent = T, opacityDim = I(1))%>%
    hide_legend()
  )
htmltools::browsable(ps)
# ignore this
subplot(par_plot, region_bar, nrows =2) %>%
  highlight(on="plotly_select", dynamic=T, persistent = T, opacityDim = I(1))%>%
  hide_legend()
# variable selection
ButtonsX=list()
for (i in 4:8){
  ButtonsX[[i-3]]= list(method = "restyle",
                        args = list( "x", list(olive2[[i]])),
                        label = colnames(olive2)[i])
}

ButtonsY=list()
for (i in 4:8){
  ButtonsY[[i-3]]= list(method = "restyle",
                        args = list( "y", list(olive2[[i]])),
                        label = colnames(olive2)[i])
}

ButtonsZ=list()
for (i in 4:8){
  ButtonsZ[[i-3]]= list(method = "restyle",
                        args = list( "z", list(olive2[[i]])),
                        label = colnames(olive2)[i])
}

plot3d <- plot_ly(shared2,x=~oleic, y=~linolenic, z=~palmitic)%>%
  add_markers() %>%
  layout(xaxis=list(title=""), yaxis=list(title="", zaxis =list(titles="")),
    title = "3d Scatter plot",
    updatemenus = list(
      list(x=0.07, y=0.6, buttons = ButtonsX, showactive = TRUE, method = "update" ),
      list(x =0.07, y=0.7, buttons = ButtonsY, showactive = TRUE, method = "update" ),
      list(x =0.07, y= .8, buttons = ButtonsZ, showactive = TRUE, method = "update" )
    ),
    annotations = list(
      list(text = "X", x= 0, y = 0.6, showarrow = FALSE),
      list(text = "Y", x = 0, y = 0.7, showarrow = FALSE),
      list(text = "Z", x = 0, y = .8, showarrow = FALSE)
    )
  
  )

plot3d

References

LS0tDQp0aXRsZTogIlZpc3VhbGl6YXRpb24gTGFiIDUiDQphdXRob3I6ICJSb3NobmkgU3VuZGFyYW11cnRoeSAocm9zc3U4MDkpICYgQnJpYW4gTWFzaW5kZSAoYnJpbWE3NDgpIg0KZGF0ZTogIjA0IE9jdG9iZXIgMjAxOCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0aGVtZTogam91cm5hbA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCmZvbnRzaXplOiAxMXB0DQojYmlibGlvZ3JhcGh5OiByZWZlcmVuY2VzLmJpYg0KLS0tDQoNCmBgYHtyIGxpYnJhcmllcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRX0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeSh0bSkNCmxpYnJhcnkod29yZGNsb3VkKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpsaWJyYXJ5KGNyb3NzdGFsaykNCmxpYnJhcnkoR0dhbGx5KQ0KbGlicmFyeShodG1sdG9vbHMpDQpgYGANCg0KIyMgQXNzaWdubWVudCAxDQoNCiMjIyAxLjENCg0KYGBge3IgZWNobz1GQUxTRX0NCmRmMTwtcmVhZC50YWJsZSgiT25lVHdvLnR4dCIsaGVhZGVyPUYsIHNlcD0nXG4nKSAjUmVhZCBmaWxlDQpkZjI8LXJlYWQudGFibGUoIkZpdmUudHh0IixoZWFkZXI9Riwgc2VwPSdcbicpDQpgYGANCg0KV29yZCBjbG91ZCBmb3IgT25lVHdvLnR4dA0KYGBge3J9DQojIHdvcmQgY2xvdWQgZm9yIE9uZVR3by50eHQNCmRmMSRkb2NfaWQ9MTpucm93KGRmMSkNCmNvbG5hbWVzKGRmMSlbMV08LSJ0ZXh0Ig0KDQojSGVyZSB3ZSBpbnRlcnByZXQgZWFjaCBsaW5lIGluIHRoZSBkb2N1bWVudCBhcyBzZXBhcmF0ZSBkb2N1bWVudA0KbXljb3JwdXMgPC0gQ29ycHVzKERhdGFmcmFtZVNvdXJjZShkZjEpKSAjQ3JlYXRpbmcgY29ycHVzIChjb2xsZWN0aW9uIG9mIHRleHQgZGF0YSkNCm15Y29ycHVzIDwtIHRtX21hcChteWNvcnB1cywgcmVtb3ZlUHVuY3R1YXRpb24pDQpteWNvcnB1cyA8LSB0bV9tYXAobXljb3JwdXMsIGZ1bmN0aW9uKHgpIHJlbW92ZVdvcmRzKHgsIHN0b3B3b3JkcygiZW5nbGlzaCIpKSkNCnRkbSA8LSBUZXJtRG9jdW1lbnRNYXRyaXgobXljb3JwdXMpICNDcmVhdGluZyB0ZXJtLWRvY3VtZW50IG1hdHJpeA0KbSA8LSBhcy5tYXRyaXgodGRtKQ0KDQojaGVyZSB3ZSBtZXJnZSBhbGwgcm93cw0KdiA8LSBzb3J0KHJvd1N1bXMobSksZGVjcmVhc2luZz1UUlVFKSAjU3VtIHVwIHRoZSBmcmVxdWVuY2llcyBvZiBlYWNoIHdvcmQNCmQgPC0gZGF0YS5mcmFtZSh3b3JkID0gbmFtZXModiksZnJlcT12KSAjQ3JlYXRlIG9uZSBjb2x1bW49bmFtZXMsIHNlY29uZD1mcmVxdWVuY2VzDQpwYWwgPC0gYnJld2VyLnBhbCg4LCJEYXJrMiIpDQpwYWwgPC0gcGFsWy0oMToyKV0gI0NyZWF0ZSBwYWxldHRlIG9mIGNvbG9ycw0Kd29yZGNsb3VkKGQkd29yZCxkJGZyZXEsIHNjYWxlPWMoOCwuMyksbWluLmZyZXE9MixtYXgud29yZHM9MTAwLCByYW5kb20ub3JkZXI9Riwgcm90LnBlcj0uMTUsIGNvbG9ycz1wYWwsIHZmb250PWMoInNhbnMgc2VyaWYiLCJwbGFpbiIpKQ0KYGBgDQoNCldvcmQgY2xvdWQgZm9yIEZpdmUudHh0DQpgYGB7cn0NCiMgd29yZGNsb3VkIGZvciBGaXZlLnR4dA0KDQpkZjIkZG9jX2lkPTE6bnJvdyhkZjIpDQpjb2xuYW1lcyhkZjIpWzFdPC0idGV4dCINCg0KI0hlcmUgd2UgaW50ZXJwcmV0IGVhY2ggbGluZSBpbiB0aGUgZG9jdW1lbnQgYXMgc2VwYXJhdGUgZG9jdW1lbnQNCm15Y29ycHVzIDwtIENvcnB1cyhEYXRhZnJhbWVTb3VyY2UoZGYyKSkgI0NyZWF0aW5nIGNvcnB1cyAoY29sbGVjdGlvbiBvZiB0ZXh0IGRhdGEpDQpteWNvcnB1cyA8LSB0bV9tYXAobXljb3JwdXMsIHJlbW92ZVB1bmN0dWF0aW9uKQ0KbXljb3JwdXMgPC0gdG1fbWFwKG15Y29ycHVzLCBmdW5jdGlvbih4KSByZW1vdmVXb3Jkcyh4LCBzdG9wd29yZHMoImVuZ2xpc2giKSkpDQp0ZG0gPC0gVGVybURvY3VtZW50TWF0cml4KG15Y29ycHVzKSAjQ3JlYXRpbmcgdGVybS1kb2N1bWVudCBtYXRyaXgNCm0gPC0gYXMubWF0cml4KHRkbSkNCg0KI2hlcmUgd2UgbWVyZ2UgYWxsIHJvd3MNCnYgPC0gc29ydChyb3dTdW1zKG0pLGRlY3JlYXNpbmc9VFJVRSkgI1N1bSB1cCB0aGUgZnJlcXVlbmNpZXMgb2YgZWFjaCB3b3JkDQpkIDwtIGRhdGEuZnJhbWUod29yZCA9IG5hbWVzKHYpLGZyZXE9dikgI0NyZWF0ZSBvbmUgY29sdW1uPW5hbWVzLCBzZWNvbmQ9ZnJlcXVlbmNlcw0KcGFsIDwtIGJyZXdlci5wYWwoNSwiRGFyazIiKQ0KcGFsIDwtIHBhbFstKDE6MildICNDcmVhdGUgcGFsZXR0ZSBvZiBjb2xvcnMNCndvcmRjbG91ZChkJHdvcmQsZCRmcmVxLCBzY2FsZT1jKDgsLjMpLG1pbi5mcmVxPTIsbWF4LndvcmRzPTEwMCwgcmFuZG9tLm9yZGVyPUYsIHJvdC5wZXI9LjE1LCBjb2xvcnM9cGFsLCB2Zm9udD1jKCJzYW5zIHNlcmlmIiwicGxhaW4iKSkNCmBgYA0KDQojIyMgMS4yDQoNClBocmFzZSBuZXRzIGZvciBGaXZlLlR4dCBhbmQgT25lVHdvLlR4dCB3aXRoIGNvbm5lY3RvciB3b3Jkcw0KDQohW1BocmFzZSBuZXQgZm9yIEZpdmUudHh0XShGaXZlLnBuZykNCg0KIVtQaHJhc2UgbmV0IGZvciBPbmVUd28udHh0XShPbmVUd28ucG5nKQ0KDQoNCiMjIyAxLjMNCg0KV29yZCBUcmVlcw0KDQoNCiMjIEFzc2lnbm1lbnQgMg0KDQpgYGB7ciBkYXRhLCBlY2hvID0gVFJVRX0NCiMgT2xpdmUgZGF0YQ0Kb2xpdmUgPC0gcmVhZC5jc3YoIm9saXZlLmNzdiIsIHNlcCA9ICIsIiwgaGVhZGVyID0gVFJVRSkNCg0KIyBjb252ZXJ0IHJlZ2lvbiB0byBmYWN0b3INCm9saXZlJFJlZ2lvbiA8LWFzLmZhY3RvcihvbGl2ZSRSZWdpb24pDQpgYGANCg0KYGBge3Igc2hhcmVkfQ0Kb2xpdmVfc2hhcmVkIDwtIFNoYXJlZERhdGEkbmV3KG9saXZlKQ0KYGBgDQoNCg0KIyMjIDIuMQ0KDQpgYGB7ciBzY2F0dGVycGxvdCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0V9DQplaWNfbGluX3NjYXR0IDwtIG9saXZlX3NoYXJlZCAlPiUgDQogIHBsb3RfbHkoeCA9IH5saW5vbGVpYywgeSA9fiBlaWNvc2Vub2ljKSAjJT4lDQogICNhZGRfbWFya2VycyhsaXN0KHNpemUgPSA2LCBjb2xvciA9ICJvcmFuZ2UiKSkNCmBgYA0KDQpXZSBmb3VuZCwgZm9yIHVudXN1YWxseSBsb3cgb2JzZXJ2YXRpb25zIG9mIEVpY29zZW5vaWMgaXQgdGFrZXMgdGhlIHZhbHVlcyBvZiAxLDIsYW5kIDMuDQoNCiMjIyAyLjINCg0KYGBge3IgYmFyY2hhcnR9DQpiYXJfY2hhcnQgPC0gb2xpdmVfc2hhcmVkICU+JQ0KICBwbG90X2x5KCB4ID1+IFJlZ2lvbikgJT4lDQogIGFkZF9oaXN0b2dyYW0oKSAlPiUNCiAgbGF5b3V0KGJhcm1vZGUgPSAib3ZlcmxheSIpDQoNCmJhcl9jaGFydA0KYGBgDQoNCg0KYGBge3IgbGlua30NCiMgbGlua2luZyB0aGUgc2NhdHRlcnBsb3QgYW5kIGJhciBjaGFydA0Kc3VicGxvdChlaWNfbGluX3NjYXR0LCBiYXJfY2hhcnQpICU+JQ0KICBoaWdobGlnaHQob24gPSAicGxvdGx5X3NlbGVjdCIsIGR5bmFtaWMgPSBULCBwZXJzaXN0ZW50ID0gVCwgb3BhY2l0eURpbSA9IEkoMSkpICU+JQ0KICBoaWRlX2xlZ2VuZCgpDQoNCmJzY29scyh3aWR0aHM9YygyLCBOQSksZmlsdGVyX3NsaWRlcigiUyIsICJTdGVhcmljIiwgb2xpdmVfc2hhcmVkLCB+c3RlYXJpYykNCiAgICAgICAgLHN1YnBsb3QoZWljX2xpbl9zY2F0dCwgYmFyX2NoYXJ0KSU+JQ0KICBoaWdobGlnaHQob249InBsb3RseV9zZWxlY3QiLCBkeW5hbWljPVQsIHBlcnNpc3RlbnQgPSBULCBvcGFjaXR5RGltID0gSSgxKSklPiVoaWRlX2xlZ2VuZCgpKQ0KYGBgDQoNCiMjIyAyLjMNCg0KYGBge3J9DQphcmFfbGluX3NjYXR0IDwtIG9saXZlX3NoYXJlZCAlPiUgDQogIHBsb3RfbHkoeCA9IH5saW5vbGVuaWMsIHkgPX4gYXJhY2hpZGljKQ0KDQpzdWJwbG90KGVpY19saW5fc2NhdHQsIGFyYV9saW5fc2NhdHQpICU+JQ0KICBoaWdobGlnaHQob24gPSAicGxvdGx5X3NlbGVjdCIsIGR5bmFtaWMgPSBULCBwZXJzaXN0ZW50ID0gVCwgb3BhY2l0eURpbSA9IEkoMSkpICU+JQ0KICBoaWRlX2xlZ2VuZCgpDQpgYGANCg0KIyMjIDIuNA0KDQpgYGB7ciBwYXJjb29yZH0NCiMgdGhlIGVpZ2h0IGFjaWRzIChjb2x1bW4gNDoxMSkNCnBhcmNvcmQgPC0gZ2dwYXJjb29yZChvbGl2ZSwgY29sdW1ucyA9IGMoMzoxMCkpDQpgYGANCg0KYGBge3IgcGxvdGx5ZGF0YX0NCiMgcGxvdGx5X2RhdGEgcmV0dXJucyBkYXRhIGFzc29jaWF0ZWQgd2l0aCBhIHBsb3RseSB2aXN1YWxpemF0aW9uLg0KcF9kYXRhIDwtIHBsb3RseV9kYXRhKGdncGxvdGx5KHBhcmNvcmQpKSAlPiUgZ3JvdXBfYnkoLklEKQ0KYGBgDQoNCmBgYHtyIHNoYXJlZDEsIGVjaG89RkFMU0V9DQojIGRhdGEgZm9yIGNyb3NzdGFsaw0Kc2hhcmVkMTwtU2hhcmVkRGF0YSRuZXcocF9kYXRhLCB+LklELCBncm91cCA9ICJPbGl2ZSIpDQpgYGANCg0KYGBge3IgcGFyY29yZHN9DQpwYXJfcGxvdCA8LSBwbG90X2x5KHNoYXJlZDEsIHggPSB+dmFyaWFibGUsIHkgPX52YWx1ZSkgJT4lDQogIGFkZF9saW5lcyhsaW5lID0gbGlzdCh3aWR0aCA9IDAuMykpICU+JQ0KICBhZGRfbWFya2VycyhtYXJrZXIgPSBsaXN0KHNpemUgPSAwLjMpLA0KICAgICAgICAgICAgICB0ZXh0ID0gfi5JRCwgaG92ZXJpbmZvID0gInRleHQiKSANCg0KYGBgDQoNCmBgYHtyIGFsbHNoYXJlZCwgZWNobyA9IEZBTFNFfQ0KIyBzdWJzZXQNCm9saXZlMiA8LSBvbGl2ZQ0KDQojIGNyZWF0ZSBhbiBpZA0Kb2xpdmUyJC5JRCA8LSAxOm5yb3cob2xpdmUpDQoNCiMgc2hhcmVkIGRhdGEgMg0Kc2hhcmVkMiA8LSBTaGFyZWREYXRhJG5ldyhvbGl2ZTIsIH4uSUQsIGdyb3VwID0gIm9saXZlIikNCmBgYA0KDQpgYGB7ciByZWdpb24sIGVjaG89RkFMU0V9DQojIGJhciBncmFwaCBvZiByZWdpb24NCnJlZ2lvbl9iYXIgPC0gc2hhcmVkMiAlPiUNCiAgcGxvdF9seSggeCA9fiBSZWdpb24pICU+JQ0KICBhZGRfaGlzdG9ncmFtKCkgJT4lDQogIGxheW91dChiYXJtb2RlID0gIm92ZXJsYXkiKQ0KDQpgYGANCg0KDQpgYGB7ciBicnVzaGluZzB9DQpic2NvbHMocGFyX3Bsb3QlPiVoaWdobGlnaHQob249InBsb3RseV9zZWxlY3QiLCBkeW5hbWljPVQsIHBlcnNpc3RlbnQgPSBULCBvcGFjaXR5RGltID0gSSgxKSklPiUNCiAgICAgICAgIGhpZGVfbGVnZW5kKCksDQogICAgICAgcmVnaW9uX2JhciU+JWhpZ2hsaWdodChvbj0icGxvdGx5X2NsaWNrIiwgZHluYW1pYz1ULCBwZXJzaXN0ZW50ID0gVCklPiVoaWRlX2xlZ2VuZCgpKQ0KYGBgDQoNCg0KYGBge3IgYnJ1c2hpbmcxLCBldmFsPUZBTFNFfQ0KcHM8LWh0bWx0b29sczo6dGFnTGlzdChwYXJfcGxvdCU+JQ0KICBoaWdobGlnaHQob249InBsb3RseV9zZWxlY3QiLCBkeW5hbWljPVQsIHBlcnNpc3RlbnQgPSBULCBvcGFjaXR5RGltID0gSSgxKSklPiUNCiAgaGlkZV9sZWdlbmQoKSwNCiAgcmVnaW9uX2JhciU+JQ0KICAgIGhpZ2hsaWdodChvbj0icGxvdGx5X2NsaWNrIiwgZHluYW1pYz1ULCBwZXJzaXN0ZW50ID0gVCwgb3BhY2l0eURpbSA9IEkoMSkpJT4lDQogICAgaGlkZV9sZWdlbmQoKQ0KICApDQpodG1sdG9vbHM6OmJyb3dzYWJsZShwcykNCmBgYA0KDQoNCmBgYHtyIGJydXNoaW5nMiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0UsIGV2YWw9RkFMU0V9DQojIGlnbm9yZSB0aGlzDQpzdWJwbG90KHBhcl9wbG90LCByZWdpb25fYmFyLCBucm93cyA9MikgJT4lDQogIGhpZ2hsaWdodChvbj0icGxvdGx5X3NlbGVjdCIsIGR5bmFtaWM9VCwgcGVyc2lzdGVudCA9IFQsIG9wYWNpdHlEaW0gPSBJKDEpKSU+JQ0KICBoaWRlX2xlZ2VuZCgpDQpgYGANCg0KYGBge3IgM2RwbG90LCBlY2hvPUZBTFNFfQ0KIyB2YXJpYWJsZSBzZWxlY3Rpb24NCkJ1dHRvbnNYPWxpc3QoKQ0KZm9yIChpIGluIDQ6OCl7DQogIEJ1dHRvbnNYW1tpLTNdXT0gbGlzdChtZXRob2QgPSAicmVzdHlsZSIsDQogICAgICAgICAgICAgICAgICAgICAgICBhcmdzID0gbGlzdCggIngiLCBsaXN0KG9saXZlMltbaV1dKSksDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IGNvbG5hbWVzKG9saXZlMilbaV0pDQp9DQoNCkJ1dHRvbnNZPWxpc3QoKQ0KZm9yIChpIGluIDQ6OCl7DQogIEJ1dHRvbnNZW1tpLTNdXT0gbGlzdChtZXRob2QgPSAicmVzdHlsZSIsDQogICAgICAgICAgICAgICAgICAgICAgICBhcmdzID0gbGlzdCggInkiLCBsaXN0KG9saXZlMltbaV1dKSksDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IGNvbG5hbWVzKG9saXZlMilbaV0pDQp9DQoNCkJ1dHRvbnNaPWxpc3QoKQ0KZm9yIChpIGluIDQ6OCl7DQogIEJ1dHRvbnNaW1tpLTNdXT0gbGlzdChtZXRob2QgPSAicmVzdHlsZSIsDQogICAgICAgICAgICAgICAgICAgICAgICBhcmdzID0gbGlzdCggInoiLCBsaXN0KG9saXZlMltbaV1dKSksDQogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IGNvbG5hbWVzKG9saXZlMilbaV0pDQp9DQoNCnBsb3QzZCA8LSBwbG90X2x5KHNoYXJlZDIseD1+b2xlaWMsIHk9fmxpbm9sZW5pYywgej1+cGFsbWl0aWMpJT4lDQogIGFkZF9tYXJrZXJzKCkgJT4lDQogIGxheW91dCh4YXhpcz1saXN0KHRpdGxlPSIiKSwgeWF4aXM9bGlzdCh0aXRsZT0iIiwgemF4aXMgPWxpc3QodGl0bGVzPSIiKSksDQogICAgdGl0bGUgPSAiM2QgU2NhdHRlciBwbG90IiwNCiAgICB1cGRhdGVtZW51cyA9IGxpc3QoDQogICAgICBsaXN0KHg9MC4wNywgeT0wLjYsIGJ1dHRvbnMgPSBCdXR0b25zWCwgc2hvd2FjdGl2ZSA9IFRSVUUsIG1ldGhvZCA9ICJ1cGRhdGUiICksDQogICAgICBsaXN0KHggPTAuMDcsIHk9MC43LCBidXR0b25zID0gQnV0dG9uc1ksIHNob3dhY3RpdmUgPSBUUlVFLCBtZXRob2QgPSAidXBkYXRlIiApLA0KICAgICAgbGlzdCh4ID0wLjA3LCB5PSAuOCwgYnV0dG9ucyA9IEJ1dHRvbnNaLCBzaG93YWN0aXZlID0gVFJVRSwgbWV0aG9kID0gInVwZGF0ZSIgKQ0KICAgICksDQogICAgYW5ub3RhdGlvbnMgPSBsaXN0KA0KICAgICAgbGlzdCh0ZXh0ID0gIlgiLCB4PSAwLCB5ID0gMC42LCBzaG93YXJyb3cgPSBGQUxTRSksDQogICAgICBsaXN0KHRleHQgPSAiWSIsIHggPSAwLCB5ID0gMC43LCBzaG93YXJyb3cgPSBGQUxTRSksDQogICAgICBsaXN0KHRleHQgPSAiWiIsIHggPSAwLCB5ID0gLjgsIHNob3dhcnJvdyA9IEZBTFNFKQ0KICAgICkNCiAgDQogICkNCg0KcGxvdDNkDQpgYGANCg0KDQoNCiMjIyBBcHBlbmRpeA0KDQpgYGB7ciByZWYubGFiZWw9a25pdHI6OmFsbF9sYWJlbHMoKSwgZWNobyA9IFQsIGV2YWwgPSBGfQ0KDQpgYGANCg0KIyMjIFJlZmVyZW5jZXM=